﻿#pragma execution_character_set("utf-8")
#include "ZFtpDemoDialog.h"
#include "ui_ZFtpDemoDialog.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QTextCodec>
#include <QTreeWidgetItem>

static const QString GetIniPath()
{
    const QString path = QCoreApplication::applicationDirPath() + "/FtpUpload.ini";
    return path;
}

ZFtpDemoDialog::ZFtpDemoDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ZFtpDemoDialog)
{
    ui->setupUi(this);

    initWidget();
}

ZFtpDemoDialog::~ZFtpDemoDialog()
{
    delete ui;
}


//登录
void ZFtpDemoDialog::on_pushButton_Login_clicked()
{
    //连接
    m_connect_to_host_request.reset(new ZFtpNS::ConnectToHostRequest);
    m_connect_to_host_request->setConnectInfo(ui->lineEdit_Host->text(),ui->lineEdit_Port->text().toInt());
    m_connect_to_host_response = m_zftp.connectToHost(m_connect_to_host_request);
    //登录
    m_login_request.reset(new ZFtpNS::LoginRequest);
    m_login_request->setLoginInfo(ui->lineEdit_User->text(), ui->lineEdit_pad->text());
    m_login_response = m_zftp.login(m_login_request);

    connect(m_login_response.data(), SIGNAL(sigResult(bool)), SLOT(slotLoginFtpResult(bool)));
    connect(m_connect_to_host_response.data(), SIGNAL(sigResult(bool)), SLOT(slotConnectToHostResult(bool)));
}

//退出
void ZFtpDemoDialog::on_pushButton_Quit_clicked()
{
    m_close_request.reset(new ZFtpNS::CloseFtpRequest);
    m_close_response = m_zftp.close(m_close_request);
    connect(m_close_response.data(), SIGNAL(sigResult(bool)), SLOT(slotCloseFtpResult(bool)));
}

//刷新
void ZFtpDemoDialog::on_pushButton_Refush_clicked()
{
    lsDir();
}

//返回
void ZFtpDemoDialog::on_pushButton_Back_clicked()
{
    ui->treeWidget->clear();
    isDirectory.clear();
    QString strLeft = m_severCurrentPath.left(m_severCurrentPath.lastIndexOf('/'));
    m_severCurrentPath     = strLeft;
    ui->label_SeverPath->setText(QString("服务器路径：%1").arg(m_severCurrentPath));
    if (m_severCurrentPath.isEmpty()) {
        //cdDir(QString::fromLocal8Bit("/"));
    }
    else {
        cdDir(m_severCurrentPath);

    }
    sleep(1);
    lsDir();
}

//上传文件
void ZFtpDemoDialog::on_uploadButton_clicked()
{

}

//上传文件夹
void ZFtpDemoDialog::on_uploadButton_All_clicked()
{
    auto dirPath = ui->lineEdit_dir->text();
    UploadDir( dirPath);
}

//取消操作
void ZFtpDemoDialog::on_cancelBtn_clicked()
{
    m_zftp.abort();
}

//获取文件路径
void ZFtpDemoDialog::on_toolButton_file_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(
        this, QString::fromLocal8Bit("打开文件..."), ".", "*");
    if (fileName.isNull())
        return;

    if (!QFile::exists(fileName))
    {
        return;
    }

    ui->lineEdit_path->setText(fileName);
}

//获取文件夹路径
void ZFtpDemoDialog::on_toolButton_dir_clicked()
{
    auto path = QFileDialog::getExistingDirectory(this);
    ui->lineEdit_dir->setText(path);
}


void ZFtpDemoDialog::slotConnectToHostResult(bool result)
{
    QString log = QStringLiteral("连接Ftp结果: %1, 错误信息：%2")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"))
            .arg(m_connect_to_host_response->lastErrorString());
    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);

}

void ZFtpDemoDialog::slotCloseFtpResult(bool result)
{
    QString log = QStringLiteral("关闭Ftp结果: %1")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"));

    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);
}

void ZFtpDemoDialog::slotLoginFtpResult(bool result)
{
    QString log = QStringLiteral("登录Ftp结果: %1")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"));
    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);
}

void ZFtpDemoDialog::slotCdDirFtpResult(bool result)
{
    QString log = QStringLiteral("进入Ftp目录结果: %1")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"));
    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);
}

void ZFtpDemoDialog::slotUploadFileProgress(qint64 done, qint64 total)
{
    ui->progressBar->setVisible(true);
    qreal progress = done * 1.0 / total * 100;
    ui->progressBar->setValue(progress);
}

void ZFtpDemoDialog::slotUploadFileResult(bool result)
{
    QString log = QStringLiteral("上传文件结果: %1")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"));
    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);
    if (m_loop.isRunning())
        m_loop.quit();
    ui->progressBar->setValue(0);
    ui->progressBar->setVisible(false);
}

void ZFtpDemoDialog::slotListInfo(QUrlInfo urlInfo)
{
    QString fileSize; // 用于存储文件大小，根据文件大小字节，设置文件在树列表的单位

    if (urlInfo.size() >= 0 && urlInfo.size() < 1024)
    {
        fileSize = QString::number(urlInfo.size()) + "Byte";
    }
    else if (urlInfo.size() >= 1024 && urlInfo.size() < 1024 * 1024)
    {
        fileSize = QString::number(urlInfo.size() / 1024.0, 'f', 2) + "KB";
    }
    else if (urlInfo.size() >= 1024 * 1024 && urlInfo.size() < 1024 * 1024 * 1024)
    {
        fileSize = QString::number(urlInfo.size() / 1024 / 1024.0, 'f', 2) + "MB";
    }
    else if (urlInfo.size() >= 1024 * 1024 * 1024)
    {
        fileSize = QString::number(urlInfo.size() / 1024 / 1024 / 1024.0, 'f', 2) + "GB";
    }

    QTreeWidgetItem* item = new QTreeWidgetItem;

    item->setText(0, urlInfo.name());
    item->setText(1, fileSize);
    item->setText(2, urlInfo.lastModified().toString("yyyy/MM/dd hh:mm"));

    QPixmap pixmap(urlInfo.isDir() ? ":/img/dir.png" :
                                     ":/img/file.png");
    item->setIcon(0, pixmap);
    isDirectory[urlInfo.name()] = urlInfo.isDir();
    ui->treeWidget->addTopLevelItem(item);
    if (!ui->treeWidget->currentItem()) {
        ui->treeWidget->setCurrentItem(ui->treeWidget->topLevelItem(0));
        ui->treeWidget->setEnabled(true);
    }
}

void ZFtpDemoDialog::slotListInfoResult(bool result)
{
    QString log = QStringLiteral("列出目录结果: %1")
            .arg(result ? QStringLiteral("成功") : QStringLiteral("失败"));
    result ? LogOutput_TextBrowser(log,2) : LogOutput_TextBrowser(log,1);
}

void ZFtpDemoDialog::on_comboBox_coding_currentIndexChanged(const QString &arg1)
{
    if(arg1 == "UTF-8")
    {
        m_zftp.setFtpServerTextCodec("UTF-8");
        LogOutput_TextBrowser(QString("当前编码：%1").arg(m_zftp.ftpServerTextCodec()));
    }
    else if(arg1 == "GB2312")
    {
        m_zftp.setFtpServerTextCodec("GB2312");
        LogOutput_TextBrowser(QString("当前编码：%1").arg(m_zftp.ftpServerTextCodec()));
    }
}

void ZFtpDemoDialog::DoubleClicked_processItem(QTreeWidgetItem *item, int column)
{

    QString DirNameStr = item->text(0);
    if (isDirectory.value(DirNameStr))
    {
        ui->treeWidget->clear();
        isDirectory.clear();
        m_severCurrentPath += QString::fromLocal8Bit("/") + DirNameStr;
        cdDir(m_severCurrentPath);
        ui->label_SeverPath->setText(QString("服务器路径：%1").arg(m_severCurrentPath));
        sleep(1);
        lsDir();
        return;
    }
}

void ZFtpDemoDialog::on_treeWidget_customContextMenuRequested(const QPoint)
{
    static int status = 1;
    if (status == 1) {
        popMenu = new QMenu(this); // 定义一个右键弹出菜单
        cdToParent = popMenu->addAction(QString("返回上一级"));
        upload   = popMenu->addAction(QString("上传"));
        download = popMenu->addAction(QString("下载"));
        popMenu->addSeparator(); // 插入一个分割线
        reName = popMenu->addAction(QString("重命名"));
        createFolder = popMenu->addAction(QString("新建文件夹"));
        popMenu->addSeparator();
        removeFile = popMenu->addAction(QString("删除文件"));
        removeFolder = popMenu->addAction(QString("删除文件夹"));
        popMenu->addSeparator();
        refresh = popMenu->addAction(QString("刷新"));
        if (ui->treeWidget->topLevelItemCount() == 0) // 根节点为空
        {
            upload->setEnabled(false);
            download->setEnabled(false);
            reName->setEnabled(false);
            createFolder->setEnabled(false);
            removeFile->setEnabled(false);
            removeFolder->setEnabled(false);
            refresh->setEnabled(false);
        }

        popMenu->exec(QCursor::pos()); // 弹出右键菜单，菜单位置为光标位置
        popMenu->clear();
        delete popMenu;
        popMenu = nullptr;
    }
    else {
    }
    status *= -1;
}

void ZFtpDemoDialog::FtpStateChange(int state)
{
    switch (state) {
    case QFtp::Unconnected :
        ui->label_state->setText("状态：未连接");
        ui->label_state->setStyleSheet("color: red");
        break;
    case QFtp::HostLookup :
        ui->label_state->setText("状态：查找IP");
        ui->label_state->setStyleSheet("color: blue");
        break;
    case QFtp::Connecting :
        ui->label_state->setText("状态：正在连接");
        ui->label_state->setStyleSheet("color: blue");
        break;
    case QFtp::Connected :
        ui->label_state->setText("状态：已连接");
        ui->label_state->setStyleSheet("color: green");
        break;
    case QFtp::LoggedIn :
        ui->label_state->setText("状态：已登录");
        ui->label_state->setStyleSheet("color: green");
        break;
    case QFtp::Closing :
        ui->label_state->setText("状态：已关闭");
        ui->label_state->setStyleSheet("color: red");;
        break;
    default:
        break;
    }
}

void ZFtpDemoDialog::closeEvent(QCloseEvent *event)
{
    if(m_zftp.state() == 4)
        on_pushButton_Quit_clicked();
    sleep(1);

    WriteDefaultPath();
    return QWidget::closeEvent(event);
}

//初始化界面
void ZFtpDemoDialog::initWidget()
{
    ReadDefaultPath();

    //加载CSS文件
    QFile styleFile(QString(":/qss/red.css"));
    if (styleFile.open(QFile::ReadOnly)) {
        QString styleStr = styleFile.readAll();
        qApp->setStyleSheet(styleStr);
        styleFile.close();
    }

    QStringList topTitle;
    topTitle << "名称"  << "文件大小" << "文件日期";
    ui->treeWidget->setHeaderLabels(topTitle);
    // TreeWidget 自动列宽
    //ui->treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    ui->treeWidget->setColumnWidth(0,200);
    ui->treeWidget->setColumnWidth(1,150);
    ui->treeWidget->setColumnWidth(2,150);
    ui->progressBar->setVisible(false);

    ui->comboBox_coding->addItem("GB2312");
    ui->comboBox_coding->addItem("UTF-8");
    ui->comboBox_coding->setCurrentIndex(1);

    connect(ui->treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
            this, SLOT(DoubleClicked_processItem(QTreeWidgetItem*, int)));
    connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
            SLOT(on_treeWidget_customContextMenuRequested(QPoint)));
    connect(&m_zftp,SIGNAL(sigFtpStateChanged(int)),this,SLOT(FtpStateChange(int)));

    int state = m_zftp.state();
    FtpStateChange(state);
}

void ZFtpDemoDialog::ReadDefaultPath()
{
    QString    path   = GetIniPath();
    QSettings* config = new QSettings(path, QSettings::IniFormat);
    config->setIniCodec(QTextCodec::codecForName("UTF-8"));

    ui->lineEdit_Host->setText(config->value(QString("Login/Host")).toString());
    ui->lineEdit_Port->setText(config->value(QString("Login/port")).toString());
    ui->lineEdit_User->setText(config->value(QString("Login/UserName")).toString());
    ui->lineEdit_pad->setText(config->value(QString("Login/PassWord")).toString());

    ui->checkBox->setChecked(config->value(QString("Checked/LoginChecked")).toBool());
    ui->radioButtonActive->setChecked(config->value(QString("Checked/ModeCheckedInitiative")).toBool());
    ui->radioButtonPassive->setChecked(config->value(QString("Checked/ModeCheckedPassive")).toBool());

    ui->lineEdit_path->setText(config->value(QString("Path/SourceFilePath")).toString());
    ui->lineEdit_dir->setText(config->value(QString("Path/SourceDirPath")).toString());

    ui->label_SeverPath->setText(QString("服务器路径：").arg(m_severCurrentPath));
    on_checkBox_clicked(config->value(QString("Checked/LoginChecked")).toBool());

}

void ZFtpDemoDialog::WriteDefaultPath()
{
    QString    path   = GetIniPath();
    QSettings* config = new QSettings(path, QSettings::IniFormat);
    config->setIniCodec(QTextCodec::codecForName("UTF-8"));

    config->beginGroup(QString("Login"));
    config->setValue("Host", ui->lineEdit_Host->text());
    config->setValue("port", ui->lineEdit_Port->text());
    config->setValue("UserName", ui->lineEdit_User->text());
    config->setValue("PassWord", ui->lineEdit_pad->text());
    config->endGroup();

    config->beginGroup(QString("Checked"));
    config->setValue("LoginChecked", ui->checkBox->isChecked());
    config->setValue("ModeCheckedInitiative", ui->radioButtonActive->isChecked());
    config->setValue("ModeCheckedPassive", ui->radioButtonPassive->isChecked());
    config->endGroup();

    config->beginGroup(QString("Path"));
    config->setValue("SourceFilePath", ui->lineEdit_path->text());
    config->setValue("SourceDirPath", ui->lineEdit_dir->text());
    config->endGroup();
}

void ZFtpDemoDialog::LogOutput_TextBrowser(const QString &msg,int colorState)
{
    ui->textBrowser->setStyleSheet("QTextBrowser { background-color: white; }");
    switch (colorState) {
    case 1:
        ui->textBrowser->append(QString("<font color='red'>%2 %1</font>")
                                .arg(msg).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        break;
    case 2:
        ui->textBrowser->append(QString("<font color='blue'>%2 %1</font>")
                                .arg(msg).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        break;
    case 3:
        ui->textBrowser->append(QString("<font color='green'>%2 %1</font>")
                                .arg(msg).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        break;
    default:
        ui->textBrowser->append(QString("%2 %1")
                                .arg(msg).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        break;
    }
}

void ZFtpDemoDialog::sleep(unsigned int msec)
{
    QTime reachTime = QTime::currentTime().addMSecs(msec);

    while (QTime::currentTime() < reachTime)
    {
        QApplication::processEvents(QEventLoop::AllEvents, 100);
    }
}

void ZFtpDemoDialog::cdDir(QString dirPath)
{
    m_cddir_request.reset(new ZFtpNS::CdDirRequest);
    m_cddir_request->setFtpDirname(dirPath);
    m_cddir_response = m_zftp.cd(m_cddir_request);

    connect(m_cddir_response.data(), SIGNAL(sigResult(bool)), SLOT(slotCdDirFtpResult(bool)));
    connect(m_cddir_response.data(), SIGNAL(sigRequestQueued()), SLOT(slotCdDirRequestQueued()));
    connect(m_cddir_response.data(), SIGNAL(sigRequestStarted()), SLOT(slotCdDirRequestStarted()));
    connect(m_cddir_response.data(), SIGNAL(sigRequestFinished(bool)), SLOT(slotCdDirRequestFinished(bool)));
}

void ZFtpDemoDialog::lsDir()
{
    // 开始
    m_ls_request.reset(new ZFtpNS::ListDirRequest);
    m_ls_request->setFtpDirpath("./");
    m_ls_response = m_zftp.listDir(m_ls_request);
    ui->treeWidget->clear();
    connect(m_ls_response.data(), SIGNAL(sigListInfo(QUrlInfo)), SLOT(slotListInfo(QUrlInfo)));
    connect(m_ls_response.data(), SIGNAL(sigResult(bool)), SLOT(slotListInfoResult(bool)));
}

void ZFtpDemoDialog::UploadDir(QString dirPath)
{

    if (dirPath == "") {
        //mutex.unlock();
        return;
    }

    QDir dir(dirPath);
    if (dir.exists()) {
        auto fileLst = dir.entryInfoList(QDir::Files);
        auto end_it  = fileLst.end();
        for (auto it = fileLst.begin(); it != end_it; it++)
        {
            QFile*    file = new QFile(it->filePath(), this);
            if (!file->open(QIODevice::ReadOnly))
            {
                if (m_loop.isRunning())
                    m_loop.quit();
                delete file;
                continue;
            }

                // 开始上传
                m_ulfile_request.reset(new ZFtpNS::UploadFileRequest2);
                m_ulfile_request->setUploadParam(file, it->fileName());
                m_ulfile_response = m_zftp.uploadFile(m_ulfile_request);
                connect(m_ulfile_response.data(), SIGNAL(sigUploadProgress(qint64,qint64)), SLOT(slotUploadFileProgress(qint64,qint64)));
                connect(m_ulfile_response.data(), SIGNAL(sigResult(bool)), SLOT(slotUploadFileResult(bool)));
                m_loop.exec();
        }
    }
}

//自动登录
void ZFtpDemoDialog::on_checkBox_clicked(bool checked)
{
    if (checked == true)
    {
        on_pushButton_Login_clicked();
    }
}

void ZFtpDemoDialog::on_radioButtonActive_clicked(bool checked)
{
    if(checked == true)
        m_zftp.setTransferMode(QFtp::Active);
}

void ZFtpDemoDialog::on_radioButtonPassive_clicked(bool checked)
{
    if(checked == true)
        m_zftp.setTransferMode(QFtp::Passive);
}
